package com.cyzy.homework.service.impl;

import com.cyzy.homework.dto.LeaveRequestDTO;
import com.cyzy.homework.entity.LeaveRequest;
import com.cyzy.homework.repository.LeaveRequestRepository;
import com.cyzy.homework.service.LeaveRequestService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 请假申请服务实现类
 */
@Service
@Transactional
public class LeaveRequestServiceImpl implements LeaveRequestService {
    
    @Autowired
    private LeaveRequestRepository leaveRequestRepository;
    
    @Override
    public LeaveRequestDTO submitLeaveRequest(LeaveRequestDTO leaveRequestDTO) {
        // 验证请假日期
        if (leaveRequestDTO.getStartDate().isAfter(leaveRequestDTO.getEndDate())) {
            throw new RuntimeException("开始日期不能晚于结束日期");
        }
        
        // 验证开始日期不能是过去
        if (leaveRequestDTO.getStartDate().isBefore(LocalDate.now())) {
            throw new RuntimeException("开始日期不能早于今天");
        }
        
        // 检查日期冲突
        List<LeaveRequest> conflictRequests = leaveRequestRepository.findOverlappingLeaveRequests(
            leaveRequestDTO.getUserId(),
            leaveRequestDTO.getStartDate(),
            leaveRequestDTO.getEndDate()
        );
        
        if (!conflictRequests.isEmpty()) {
            throw new RuntimeException("请假日期与已有申请冲突，请选择其他日期");
        }
        
        // 计算请假天数
        long daysBetween = ChronoUnit.DAYS.between(leaveRequestDTO.getStartDate(), leaveRequestDTO.getEndDate()) + 1;
        leaveRequestDTO.setDays((int) daysBetween);
        
        // 创建请假申请
        LeaveRequest leaveRequest = new LeaveRequest();
        BeanUtils.copyProperties(leaveRequestDTO, leaveRequest);
        leaveRequest.setStatus(0); // 待审核
        leaveRequest.setApplyTime(LocalDateTime.now());
        
        leaveRequest = leaveRequestRepository.save(leaveRequest);
        return convertToDTO(leaveRequest);
    }
    
    @Override
    @Transactional(readOnly = true)
    public LeaveRequestDTO getLeaveRequestById(Long id) {
        Optional<LeaveRequest> optionalLeaveRequest = leaveRequestRepository.findById(id);
        if (!optionalLeaveRequest.isPresent()) {
            throw new RuntimeException("请假申请不存在");
        }
        return convertToDTO(optionalLeaveRequest.get());
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<LeaveRequestDTO> getLeaveRequestsByUserId(String userId, Pageable pageable) {
        Page<LeaveRequest> leaveRequestPage = leaveRequestRepository.findByUserIdOrderByApplyTimeDesc(userId, pageable);
        return leaveRequestPage.map(this::convertToDTO);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<LeaveRequestDTO> getLeaveRequestsByClassId(String classId, Pageable pageable) {
        Page<LeaveRequest> leaveRequestPage = leaveRequestRepository.findByClassIdOrderByApplyTimeDesc(classId, pageable);
        return leaveRequestPage.map(this::convertToDTO);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<LeaveRequestDTO> getLeaveRequestsByStatus(Integer status, Pageable pageable) {
        Page<LeaveRequest> leaveRequestPage = leaveRequestRepository.findByStatusOrderByApplyTimeDesc(status, pageable);
        return leaveRequestPage.map(this::convertToDTO);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<LeaveRequestDTO> getLeaveRequestsByClassIdAndStatus(String classId, Integer status, Pageable pageable) {
        Page<LeaveRequest> leaveRequestPage = leaveRequestRepository.findByClassIdAndStatusOrderByApplyTimeDesc(classId, status, pageable);
        return leaveRequestPage.map(this::convertToDTO);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<LeaveRequestDTO> getLeaveRequestsByUserIdAndStatus(String userId, Integer status, Pageable pageable) {
        Page<LeaveRequest> leaveRequestPage = leaveRequestRepository.findByUserIdAndStatusOrderByApplyTimeDesc(userId, status, pageable);
        return leaveRequestPage.map(this::convertToDTO);
    }
    
    @Override
    public LeaveRequestDTO updateLeaveRequest(Long id, LeaveRequestDTO leaveRequestDTO) {
        Optional<LeaveRequest> optionalLeaveRequest = leaveRequestRepository.findById(id);
        if (!optionalLeaveRequest.isPresent()) {
            throw new RuntimeException("请假申请不存在");
        }
        
        LeaveRequest leaveRequest = optionalLeaveRequest.get();
        
        // 只有待审核状态的申请才能修改
        if (leaveRequest.getStatus() != 0) {
            throw new RuntimeException("只有待审核状态的申请才能修改");
        }
        
        // 验证权限
        if (!leaveRequest.getUserId().equals(leaveRequestDTO.getUserId())) {
            throw new RuntimeException("无权限修改此申请");
        }
        
        // 更新信息
        leaveRequest.setLeaveType(leaveRequestDTO.getLeaveType());
        leaveRequest.setStartDate(leaveRequestDTO.getStartDate());
        leaveRequest.setEndDate(leaveRequestDTO.getEndDate());
        leaveRequest.setReason(leaveRequestDTO.getReason());
        
        // 重新计算天数
        long daysBetween = ChronoUnit.DAYS.between(leaveRequestDTO.getStartDate(), leaveRequestDTO.getEndDate()) + 1;
        leaveRequest.setDays((int) daysBetween);
        
        leaveRequest = leaveRequestRepository.save(leaveRequest);
        return convertToDTO(leaveRequest);
    }
    
    @Override
    public void deleteLeaveRequest(Long id, String userId) {
        Optional<LeaveRequest> optionalLeaveRequest = leaveRequestRepository.findById(id);
        if (!optionalLeaveRequest.isPresent()) {
            throw new RuntimeException("请假申请不存在");
        }
        
        LeaveRequest leaveRequest = optionalLeaveRequest.get();
        
        // 验证权限
        if (!leaveRequest.getUserId().equals(userId)) {
            throw new RuntimeException("无权限删除此申请");
        }
        
        // 只有待审核状态的申请才能删除
        if (leaveRequest.getStatus() != 0) {
            throw new RuntimeException("只有待审核状态的申请才能删除");
        }
        
        leaveRequestRepository.deleteById(id);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Object getUserLeaveStatistics(String userId) {
        long totalCount = leaveRequestRepository.countByUserId(userId);
        long pendingCount = leaveRequestRepository.countByUserIdAndStatus(userId, 0);
        long approvedCount = leaveRequestRepository.countByUserIdAndStatus(userId, 1);
        long rejectedCount = leaveRequestRepository.countByUserIdAndStatus(userId, 2);
        
        Map<String, Object> statistics = new HashMap<>();
        statistics.put("totalCount", totalCount);
        statistics.put("pendingCount", pendingCount);
        statistics.put("approvedCount", approvedCount);
        statistics.put("rejectedCount", rejectedCount);
        
        return statistics;
    }
    
    @Override
    @Transactional(readOnly = true)
    public Object getClassLeaveStatistics(String classId) {
        long totalCount = leaveRequestRepository.countByClassId(classId);
        long pendingCount = leaveRequestRepository.countByClassIdAndStatus(classId, 0);
        long approvedCount = leaveRequestRepository.countByClassIdAndStatus(classId, 1);
        long rejectedCount = leaveRequestRepository.countByClassIdAndStatus(classId, 2);
        
        Map<String, Object> statistics = new HashMap<>();
        statistics.put("totalCount", totalCount);
        statistics.put("pendingCount", pendingCount);
        statistics.put("approvedCount", approvedCount);
        statistics.put("rejectedCount", rejectedCount);
        
        return statistics;
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean hasDateConflict(String userId, String startDate, String endDate, Long excludeId) {
        LocalDate start = LocalDate.parse(startDate);
        LocalDate end = LocalDate.parse(endDate);
        
        List<LeaveRequest> conflictRequests = leaveRequestRepository.findOverlappingLeaveRequests(userId, start, end);
        
        // 如果有excludeId，排除指定的申请
        if (excludeId != null) {
            conflictRequests.removeIf(request -> request.getId().equals(excludeId));
        }
        
        return !conflictRequests.isEmpty();
    }
    
    /**
     * 转换为DTO
     */
    private LeaveRequestDTO convertToDTO(LeaveRequest leaveRequest) {
        LeaveRequestDTO leaveRequestDTO = new LeaveRequestDTO();
        BeanUtils.copyProperties(leaveRequest, leaveRequestDTO);
        return leaveRequestDTO;
    }
}


